package pzl.com.templatemethodpattern;

import android.util.Log;

/**
 * 烹饪菜肴
 *
 * @author zl.peng
 * @version [1.0, 2016-11-01]
 *          <p/>
 *          优点：
 *          1)模板方法模式在一个类中形式化地定义算法，而由它的子类实现细节的处理。
 *          2)模板方法是一种代码复用的基本技术。它们在类库中尤为重要，它们提取了类库中的公共行为。
 *          3)模板方法模式导致一种反向的控制结构，这种结构有时被称为“好莱坞法则” ，即“别找我们，,我们找你”通过一个父类调用其子类的操作(而不是相反的子类调用父类)，通过对子类的扩展增加新的行为，符合“开闭原则”
 *          缺点：
 *          每个不同的实现都需要定义一个子类，这会导致类的个数增加，系统更加庞大，设计也更加抽象，但是更加符合“单一职责原则”，使得类的内聚性得以提高。
 */
public abstract class Cooking {
    static final String TAG = "Cooking";

    /**
     * 制作流程（业务逻辑算法骨架，定义为final，防止子类修改算法骨架，
     * 细节步骤延迟到子类中）
     * 提取公共行为
     */
    final public void process() {
        prepareCook();

        prepareIngredients();

        prepareCookingUtensil();

        makeFire();

        cooking();

        if (loveSpicy()) {
            spicy();
        }

        serving();

        remoteMusic();
    }

    /**
     * 准备厨师(提取公共行为)
     */
    final public void prepareCook() {
        Log.w(TAG, "厨师已准备就绪");
    }

    /**
     * 准备食材
     */
    abstract void prepareIngredients();

    /**
     * 准备厨具
     */
    abstract void prepareCookingUtensil();

    /**
     * 生火
     */
    final public void makeFire() {
        Log.w(TAG, "生火完毕");
    }

    /**
     * 烹制
     */
    abstract void cooking();

    /**
     * 普通的方法（无final或abstract修饰）则称之为钩子
     * 是否吃辣
     *
     * @return
     */
    public boolean loveSpicy() {
        return false;//默认
    }

    /**
     * 上菜
     */
    final public void serving() {
        Log.w(TAG, "上菜");
    }

    /**
     * 普通的方法（无final或abstract修饰）则称之为钩子
     * 点歌营造氛围(可选可不选)
     */
    public void remoteMusic() {
        Log.w(TAG, "来电流行音乐");//默认配置
    }

    /**
     * 加辣
     */
    private void spicy() {
        Log.w(TAG, "加点辣椒");
    }

    /**
     *
     * 钩子作用：
     1)作为可选内容，子类可以重写或者置之不理
     2)让子类有机会对模板方法中即将发生的或者已经发生的步骤做出反应
     3)作为控制条件，使得子类可以影响到抽象类中的算法流程
     *
     */
}
